package com.example.mymvvmdemo.utils;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;


import com.example.mymvvmdemo.MyApplication;
import com.example.mymvvmdemo.constants.Constants;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class LogUtils {
    public static final String TAG = "VoicelinkLog";
    public static final String TAG_JSON = "Voicelink_JSON";
    public static File LogPath = new File(getLogPath() + "/push_log.txt");
    private static final String FORMAT_STR = "%S[%s] %s\n";
    private static boolean LOGABLE = true;
    private static boolean DEBUG = true; //日志打印开关
    private static boolean LOGABLE_INIT = true;
    private static boolean jsonLogAble = true; //json格式化打印手动开关
    private static ConcurrentHashMap<String, String> logCache = new ConcurrentHashMap();
    private static final Long MAX_SIZE = 10 * 1024 * 1024L; //存储的最大大小 - 100M

    //是否同意协议
    public static boolean isPrivate = true;

    public static void setIsPrivate(boolean isPrivate) {
        LogUtils.isPrivate = isPrivate;
    }

    public LogUtils() {
    }

    public static boolean isDebug() {
        return DEBUG;
    }

    public static void setFileLog(boolean enable) {
        Log.i("LogUtil", "setFileLog:" + enable);
        LOGABLE = enable;
    }

    public static String getLogPath() {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return ContextCompat.getExternalFilesDirs(
                    MyApplication.getInstance().getApplicationContext(), null)[0].getAbsolutePath() + Constants.FILES_APP;
        }
        if (Build.VERSION.SDK_INT < 29) {
            return Environment.getExternalStorageDirectory() + Constants.FILES_APP;
        } else {
            return ContextCompat.getExternalFilesDirs(
                    MyApplication.getInstance().getApplicationContext(), null)[0].getAbsolutePath() + Constants.FILES_APP;
        }

    }

    public static void setLogcatLog(boolean enable) {
        Log.i("LogUtil", "setLogcatLog:" + enable);
        DEBUG = enable;
    }

    public static void init(Context context) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return;
        }

        try {
            ActivityCompat.checkSelfPermission(context, "android.permission.WRITE_EXTERNAL_STORAGE");
            ActivityCompat.checkSelfPermission(context, "android.permission.MANAGE_EXTERNAL_STORAGE");
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
//            boolean debug = 0 != (packageInfo.applicationInfo.flags & 2); //根据debug包开关日志开关-注销直接定义控制
//            DEBUG = debug;

            //没有同意协议前，禁止日志
            if (!isPrivate) {
                return;
            }
            Log.i("LogUtil", "LogPath:" + LogPath.getPath());
            if (FileUtils.getFileLen(LogPath.getAbsolutePath()) > MAX_SIZE) {
                FileUtils.deleteFile(LogPath.getAbsolutePath());
            }

            LOGABLE_INIT = true;
        } catch (PackageManager.NameNotFoundException var3) {
        }

    }

    public static void initFileLog(Context context) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return;
        }
        try {
            LogPath = new File(getLogPath(), "push_log_" + context.getPackageName() + ".txt");
            if (FileUtils.getFileLen(LogPath.getAbsolutePath()) > MAX_SIZE) {
                FileUtils.deleteFile(LogPath.getAbsolutePath());
            }

            LOGABLE_INIT = true;
        } catch (Exception var2) {
            var2.printStackTrace();
        }

    }

    public static void setFileLogPath(File file) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return;
        }

        LOGABLE_INIT = false;
        if (file != null) {
            if (!file.exists()) {
                file.mkdirs();
            }

            if (file.exists()) {
                LogPath = new File(file, "push_log_" + MyApplication.getInstance().getPackageName() + ".txt");
                LOGABLE_INIT = true;
            }
        }

    }

    public static int v(String tag, String msgString) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.v(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 2, (Throwable) null);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }
                return Log.v(tag, "" + msg);
            }
        } catch (Exception var4) {
            var4.printStackTrace();
        }

        return 0;
    }

    public static int v(String tag, String msgString, Throwable tr) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.v(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 2, tr);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }
                return Log.v(tag, "" + msg, tr);
            }
        } catch (Exception var5) {
            var5.printStackTrace();
        }

        return 0;
    }

    public static int d(String msgString) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.d(msgString);
        }
        try {
            LogData data = writeToFile(TAG, msgString, 3, (Throwable) null);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.d(TAG, "" + msg);
            }
        } catch (Exception var4) {
            Log.d(TAG, "var4:" + var4);
        }

        return 0;
    }

    public static int d(String tag, String msgString) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.d(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 3, (Throwable) null);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.d(tag, "" + msg);
            }
        } catch (Exception var4) {
            Log.d(tag, "var4:" + var4);
        }

        return 0;
    }

    public static int d(String tag, String msgString, Throwable tr) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.d(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 3, tr);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.d(tag, "" + msg, tr);
            }
        } catch (Exception var5) {
            var5.printStackTrace();
        }

        return 0;
    }

    public static int i(String tag, String msgString) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.i(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 4, (Throwable) null);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.i(tag, "" + msg);
            }
        } catch (Exception var4) {
            var4.printStackTrace();
        }

        return 0;
    }

    public static int i(String tag, String msgString, Throwable tr) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.i(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 4, tr);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.i(tag, "" + msg, tr);
            }
        } catch (Exception var5) {
            var5.printStackTrace();
        }

        return 0;
    }

    public static int w(String tag, String msgString) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.w(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 5, (Throwable) null);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.w(tag, "" + msg);
            }
        } catch (Exception var4) {
            var4.printStackTrace();
        }

        return 0;
    }

    public static int w(String tag, String msgString, Throwable tr) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.w(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 5, tr);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.w(tag, "" + msg, tr);
            }
        } catch (Exception var5) {
            var5.printStackTrace();
        }

        return 0;
    }

    public static int e(String msgString) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.e(msgString);
        }
        try {
            LogData data = writeToFile(TAG, msgString, 3, (Throwable) null);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.d(TAG, "" + msg);
            }
        } catch (Exception var4) {
            Log.d(TAG, "var4:" + var4);
        }

        return 0;
    }

    public static int e(String tag, String msgString) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.e(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 6, (Throwable) null);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.e(tag, "" + msg);
            }
        } catch (Exception var4) {
            var4.printStackTrace();
        }

        return 0;
    }

    public static int e(String tag, String msgString, Throwable tr) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return 0;
        }
        if (Constants.LOOK_LOG) {
            //Logger.e(msgString);
        }
        try {
            LogData data = writeToFile(tag, msgString, 6, tr);
            if (data.hasLogout) {
                return data.logResult;
            }

            String msg = data.msg;
            if (DEBUG) {
                if (StrUtils.isEmpty(msg)) {
                    msg = buildMessage(msgString);
                }

                return Log.e(tag, "" + msg, tr);
            }
        } catch (Exception var5) {
            var5.printStackTrace();
        }

        return 0;
    }

    private static LogData writeToFile(String tag, String msgString, int priority, Throwable tr) {

        LogData data = new LogData();

        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return data;
        }

        String msg;
        if (LOGABLE_INIT) {
            if (LOGABLE) {
                msg = buildMessage(msgString);
                if (tr != null) {
                    writeFile(tag, msg, tr);
                    data.logResult = Log.v(tag, "" + msg, tr);
                } else {
                    writeFile(tag, msg);
                    data.logResult = Log.v(tag, "" + msg);
                }

                data.hasLogout = true;
                data.msg = msg;
            }
        } else {
            msg = buildMessage(msgString);
            data.msg = msg;
            logCache.put(msg, tag);
        }

        return data;
    }

    public static synchronized void writeFile(String tag, String msg) {
        writeFile(LogPath, tag, msg, (Throwable) null);
    }

    private static synchronized void writeFile(String tag, String msg, Throwable tr) {
        writeFile(LogPath, tag, msg, tr);
    }

    public static synchronized void writeFile(final File file, final String tag, final String msg, final Throwable tr) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return;
        }
        if (Looper.myLooper() != Looper.getMainLooper()) {
            writeFileSync(file, tag, msg, tr);
        } else {
            (new AsyncTask<String, Integer, String>() {
                protected String doInBackground(String... params) {
                    writeFileSync(file, tag, msg, tr);
                    return null;
                }
            }).execute(new String[]{""});
        }

    }

    private static void writeFileSync(File file, String tag, String msg, Throwable tr) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return;
        }
        PrintStream outputStream = null;

        try {
            FileUtils.makeDir(file.getParentFile().getPath());
            if (!file.exists()) {
                file.createNewFile();
            }

            outputStream = new PrintStream(new FileOutputStream(file, true));
            outputStream.printf("%S[%s] %s\n", getSystemTime(), tag, msg);
            if (tr != null) {
                tr.printStackTrace(outputStream);
            }
        } catch (Exception var9) {
            var9.printStackTrace();
        } finally {
            if (outputStream != null) {
                outputStream.close();
            }

        }

    }

    private static String buildMessage(String msg) {
        String caller = "<unknown>";
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return String.format(Locale.ENGLISH, "[%d] %s(%s): %s", Thread.currentThread().getId(), caller, System.currentTimeMillis(), msg);
        }

        StackTraceElement[] trace = (new Throwable()).fillInStackTrace().getStackTrace();

        for (int i = 2; i < trace.length; ++i) {
            Class<?> clazz = trace[i].getClass();
            if (!clazz.equals(LogUtils.class)) {
                String callingClass = trace[i].getClassName();
                callingClass = callingClass.substring(callingClass.lastIndexOf(46) + 1);
                callingClass = callingClass.substring(callingClass.lastIndexOf(36) + 1);
                caller = callingClass + "." + trace[i].getMethodName();
                break;
            }
        }

        return String.format(Locale.ENGLISH, "[%d] %s(%s): %s", Thread.currentThread().getId(), caller, System.currentTimeMillis(), msg);
    }

    private static String getSystemTime() {
        String str = null;
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return str;
        }
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS", Locale.CHINA);
            Date curDate = new Date(System.currentTimeMillis());
            str = formatter.format(curDate);
        } catch (Exception var3) {
            var3.printStackTrace();
        }

        return str;
    }

    public static final String LINE_SEPARATOR = System.getProperty("line.separator");

    /**
     * @param tag
     * @param isTop
     */
    public static void printLine(String tag, boolean isTop) {
        if (isTop) {
            Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════");
        } else {
            Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════");
        }
    }

    /**
     * 将json格式化打印，jsonLogAble为代码开关
     *
     * @param msg        json字符串
     * @param headString 自添加标题
     */
    public static void printJson(String msg, String headString) {
        if (!jsonLogAble) {
            return;
        }
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return;
        }
        String message;

        try {
            if (msg.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(msg);
                message = jsonObject.toString(4); //最重要的方法，就一行，返回格式化的json字符串，其中的数字4是缩进字符数
            } else if (msg.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(msg);
                message = jsonArray.toString(4);
            } else {
                message = msg;
            }
        } catch (JSONException e) {
            message = msg;
        }

        printLine(TAG_JSON, true);
        message = headString + LINE_SEPARATOR + message;
        String[] lines = message.split(LINE_SEPARATOR);
        for (String line : lines) {
            Log.d(TAG_JSON, "║ " + line);
        }
        printLine(TAG_JSON, false);
    }

    public static String intentToString(Intent intent) {
        //没有同意协议前，禁止日志
        if (!isPrivate) {
            return null;
        }
        if (intent != null) {
            StringBuilder sb = new StringBuilder();
            sb.append("Intent { ");
            String action = intent.getAction();
            if (action != null) {
                sb.append("act = ").append(action).append(",");
            }

            Set<String> categories = intent.getCategories();
            if (categories != null) {
                sb.append(" cat = [");
                Iterator<String> i = categories.iterator();
                boolean done = false;

                while (i.hasNext()) {
                    if (done) {
                        sb.append(", ");
                    }

                    done = true;
                    sb.append((String) i.next());
                }

                sb.append("]");
            }

            Uri uri = intent.getData();
            if (uri != null) {
                sb.append(" dat = ").append(uri).append(",");
            }

            String type = intent.getType();
            if (type != null) {
                sb.append(" typ = ").append(type).append(",");
            }

            int flags = intent.getFlags();
            if (flags != 0) {
                sb.append(" flg = 0x").append(Integer.toHexString(flags)).append(",");
            }

            String packageStr = intent.getPackage();
            if (packageStr != null) {
                sb.append(" pkg = ").append(packageStr).append(",");
            }

            ComponentName component = intent.getComponent();
            if (component != null) {
                sb.append(" cmp = ").append(component.flattenToShortString()).append(",");
            }

            Rect rect = intent.getSourceBounds();
            if (rect != null) {
                sb.append(" bnds = ").append(rect.toShortString()).append(",");
            }

            Bundle extras = intent.getExtras();
            if (extras != null) {
                sb.append(" extras = [");
                int i = 0;

                try {
                    Iterator var12 = extras.keySet().iterator();

                    while (var12.hasNext()) {
                        String key = (String) var12.next();
                        sb.append(key).append(" = ");
                        Object obj = extras.get(key);
                        if (obj != null && obj instanceof Bundle) {
                            sb.append(" [extras2 = [");
                            int j = 0;
                            Bundle extras2 = (Bundle) obj;
                            Iterator var17 = extras2.keySet().iterator();

                            while (var17.hasNext()) {
                                String key2 = (String) var17.next();
                                Object obj2 = extras2.get(key2);
                                sb.append(key2).append(" = ").append(obj2 instanceof byte[] ? new String((byte[]) obj2) : obj2);
                                ++j;
                                if (j <= extras2.size() - 1) {
                                    sb.append(", ");
                                }
                            }

                            sb.append("] ]");
                        } else {
                            sb.append(obj instanceof byte[] ? new String((byte[]) obj) : obj);
                        }

                        ++i;
                        if (i <= extras.size() - 1) {
                            sb.append(", ");
                        }
                    }
                } catch (Exception var20) {
                    var20.printStackTrace();
                }

                sb.append("]");
            }

            sb.append(" }");
            return sb.toString();
        } else {
            return null;
        }
    }

    private static class LogData {
        boolean hasLogout;
        int logResult;
        String msg;

        private LogData() {
        }
    }
}